package com.ziytek.web.citizen.service;

import com.google.gson.Gson;
import com.ziytek.web.citizen.config.caffeine.CaffeineUtil;
import com.ziytek.web.citizen.constant.SettingConstant;
import com.ziytek.web.citizen.mapper.BasicCabinetIpMapper;
import com.ziytek.web.citizen.model.tcp.req.TcpBatteryDetailReq;
import com.ziytek.web.citizen.model.tcp.req.TcpRealTimeReq;
import com.ziytek.web.citizen.model.tcp.req.TcpStatusReq;
import com.ziytek.web.citizen.pojo.basic.BasicCabinetIp;
import io.netty.channel.ChannelHandlerContext;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;


/***
 * WEB客户端长连接请求处理
 * @author fenghx
 * */
@Slf4j
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class ClientBatteryDetailReqService {

    public static final String TOPIC_REALTIME = "realTime";
    public static final String TOPIC_STATUS = "cabinetStatus";
    public static final String TOPIC_REAL_STATS = "batteryDetail";

    private final Gson gson;
    private final PushDataService pushDataService;
    private final WebClientService webClientService;
    private final BasicCabinetIpMapper basicCabinetIpMapper;
    private final CabinetStatusPushService cabinetStatusPushService;

    public void realTimeReq(TcpRealTimeReq req, ChannelHandlerContext ctx) {
        Assert.notNull(req, "TcpRealTimeReq 请求参数不能为空");
        Assert.notNull(req.getDoor(), "TcpRealTimeReq 请求door不能为空");
        Assert.notNull(req.getTopic(), "TcpRealTimeReq 请求topic不能为空");
        Assert.notNull(req.getCabinetNo(), "TcpRealTimeReq 请求cabinetNo不能为空");

        log.info("WEB客户端首界面实时数据查询请求：{}", gson.toJson(req));

        var topic = req.getTopic();
        if (!TOPIC_REALTIME.equals(topic)) {
            log.error("不是首界面实时数据查询请求topic:{}-{}", topic, gson.toJson(req));
            return;
        }

        var door = req.getDoor();
        var cab = req.getCabinetNo();

        //var door = pushDataService.getDoor(doorNum);

        Map<String, Object> cacheMap = new HashMap<>(16);
        cacheMap.put("req", req);
        cacheMap.put("ctx", ctx);

        webClientService.deleteCacheOldRealTime();

        var key = CaffeineUtil.CACHE_KEY_TOPIC_REALTIME_QUERY
                + CaffeineUtil.CACHE_KEY_SYMBOL
                + cab + CaffeineUtil.CACHE_KEY_SYMBOL
                + door;
        CaffeineUtil.deleteStartWith(CaffeineUtil.CACHE_KEY_TOPIC_REALTIME_QUERY);
        CaffeineUtil.set(key, cacheMap, Long.MAX_VALUE);

        // 先推送首界面的实时数据
        pushDataService.realtimeDataQueryAndPush(String.valueOf(cab));
    }

    public void batteryDetailReq(TcpBatteryDetailReq req, ChannelHandlerContext ctx) {
        Assert.notNull(req, "TcpBatteryDetailReq 请求参数不能为空");
        Assert.notNull(req.getDoor(), "TcpBatteryDetailReq 请求door不能为空");
        Assert.notNull(req.getTopic(), "TcpBatteryDetailReq 请求topic不能为空");
        Assert.notNull(req.getLineNo(), "TcpBatteryDetailReq 请求clineNo不能为空");
        Assert.notNull(req.getTimeMinute(), "TcpBatteryDetailReq 请求time不能为空");
        Assert.notNull(req.getCabinetNo(), "TcpBatteryDetailReq 请求cabinetNo不能为空");
        Assert.notNull(req.getChannelNo(), "TcpBatteryDetailReq 请求channelNo不能为空");

        log.info("WEB客户端实时曲线数据查询请求：{}", gson.toJson(req));

        var topic = req.getTopic();
        if (!TOPIC_REAL_STATS.equals(topic)) {
            log.error("不是实时曲线数据查询请求topic:{}-{}", topic, gson.toJson(req));
            return;
        }

        var door = req.getDoor();
        var lineNo = req.getLineNo();
        var cab = req.getCabinetNo();
        var channelNo = req.getChannelNo();
        var timeMinute = req.getTimeMinute();

        //var door = pushDataService.getDoor(doorNum);

        Map<String, Object> cacheMap = new HashMap<>(16);
        cacheMap.put("req", req);
        cacheMap.put("ctx", ctx);

        webClientService.deleteOldCacheStats();

        var key = CaffeineUtil.CACHE_KEY_TOPIC_REAL_STATS_QUERY
                + CaffeineUtil.CACHE_KEY_SYMBOL
                + Integer.parseInt(cab) + CaffeineUtil.CACHE_KEY_SYMBOL
                + door + CaffeineUtil.CACHE_KEY_SYMBOL
                + lineNo + CaffeineUtil.CACHE_KEY_SYMBOL
                + channelNo;
        CaffeineUtil.deleteStartWith(CaffeineUtil.CACHE_KEY_TOPIC_REAL_STATS_QUERY);
        CaffeineUtil.deleteStartWith(CaffeineUtil.CACHE_KEY_TOPIC_REAL_STATS_FIRST_PUSH);
        CaffeineUtil.set(key, cacheMap, timeMinute * 60L);

        // 查看有没有请求推送曲线数据的缓存，有者推送曲线数据
        pushDataService.statsQueryAndPush(String.valueOf(Integer.parseInt(cab)));
    }

    public void cabinetStatus(TcpStatusReq req, ChannelHandlerContext ctx) {
        Assert.notNull(req, "TcpStatusReq 请求参数不能为空");

        log.info("机柜状态数据查询请求：{}", gson.toJson(req));

        var topic = req.getTopic();
        if (!TOPIC_STATUS.equals(topic)) {
            log.error("不是机柜状态数据查询请求topic:{}-{}", topic, gson.toJson(req));
            return;
        }

        var cab = req.getCabinetNo();

        if (StringUtils.isBlank(cab)) {
            List<BasicCabinetIp> ips = basicCabinetIpMapper.queryAllByAvailable(SettingConstant.IS_AVAILABLE);
            if (!CollectionUtils.isEmpty(ips)) {
                cab = ips.getFirst().getCabinetNo();
                cab = String.valueOf(Integer.parseInt(cab));
            }
        }

        Map<String, Object> cacheMap = new HashMap<>(16);
        cacheMap.put("req", req);
        cacheMap.put("ctx", ctx);

        var key = CaffeineUtil.CACHE_KEY_TOPIC_CAB_STATUS
                + CaffeineUtil.CACHE_KEY_SYMBOL
                + cab + CaffeineUtil.CACHE_KEY_SYMBOL;
        CaffeineUtil.deleteStartWith(CaffeineUtil.CACHE_KEY_TOPIC_CAB_STATUS);
        CaffeineUtil.set(key, cacheMap, Long.MAX_VALUE);

        // 先推送首界面的实时数据
        //cabinetStatusPushService.cabinetStatusPush(cab);
        cabinetStatusPushService.cabinetStatusPush();
    }
}
